﻿using UnityEngine;
namespace NL.Advanced
{
    public static class ExpressionEx
    {
        public static bool ConditionOK(ExpressionCondition cond, int t)
        {
            return cond.Check(t);
        }
    }




    public enum OperatorType
    {
        Equal = 0,               //  =            等于
        NotEqual = 1,            //  !=   <>      不等于   

        Less = 3,                 //  <            小于
        LessEqual = 4,           //  <=           小于

        Greater = 5,             //  >            小于
        GreaterEqual = 6,        //  >=           小于

        Each = 11,               //  %            每n个  整除

        In = 21,                 //  []           包含          
        NotIn = 22,              //  [!]          不包含        

    }



    /// <summary>
    /// 条件...可以验证的  >100 <=100 !=100
    /// </summary>
    public struct ExpressionCondition
    {
        public OperatorType Operation;

        string Value;

        public int ValueAsInit;
        public Vector3 ValueAsVector;

        /// <summary>
        /// >100   <100
        /// </summary>
        /// <param name="str"></param>
        public ExpressionCondition(string str)
        {
            // 先按照 双字符拆分
            Operation = OperatorType.Equal;




            nill _Left;
            nill _Right = "";

            if (str.IndexOf("[!]") >= 0)
            {
                Operation = OperatorType.NotIn;
                NLString.LeftAndRight(str, "[!]", out _Left, out _Right);
            }
            if (str.IndexOf("[]") >= 0)
            {
                Operation = OperatorType.In;
                NLString.LeftAndRight(str, "[]", out _Left, out _Right);
            }

            if (str.IndexOf("!=") >= 0)
            {
                Operation = OperatorType.NotEqual;
                NLString.LeftAndRight(str, "!=", out _Left, out _Right);
            }
            if (str.IndexOf("<>") >= 0)
            {
                Operation = OperatorType.NotEqual;
                NLString.LeftAndRight(str, "<>", out _Left, out _Right);
            }

            if (str.IndexOf("<=") >= 0)
            {
                Operation = OperatorType.LessEqual;
                NLString.LeftAndRight(str, "<=", out _Left, out _Right);
            }
            if (str.IndexOf(">=") >= 0)
            {
                Operation = OperatorType.GreaterEqual;
                NLString.LeftAndRight(str, ">=", out _Left, out _Right);
            }


            //按照单字符 拆分
            if (str.IndexOf("=") >= 0)
            {
                Operation = OperatorType.Equal;
                NLString.LeftAndRight(str, "=", out _Left, out _Right);
            }
            if (str.IndexOf(">") >= 0)
            {
                Operation = OperatorType.Greater;
                NLString.LeftAndRight(str, ">", out _Left, out _Right);
            }
            if (str.IndexOf("<") >= 0)
            {
                Operation = OperatorType.Less;
                NLString.LeftAndRight(str, "<", out _Left, out _Right);
            }

            if (str.IndexOf("%") >= 0)
            {
                Operation = OperatorType.Each;
                NLString.LeftAndRight(str, "%", out _Left, out _Right);
            }

            Value = _Right.AsString;

            ValueAsInit = _Right.AsInt;

            ValueAsVector = _Right.AsVector();
        }
        public bool Check(string t)
        {
            if (ValueAsInit < 0) return false;
            switch (Operation)
            {
                case OperatorType.Equal: return t == Value;
                case OperatorType.NotEqual: return t != Value;
                case OperatorType.Less: return t.CompareTo(Value) < 0;
                case OperatorType.LessEqual: return t.CompareTo(Value) < 0;
                case OperatorType.Greater: return t.CompareTo(Value) > 0;
                case OperatorType.GreaterEqual: return t.CompareTo(Value) >= 0;
                case OperatorType.In:
                    return t.In(Value);
                case OperatorType.NotIn:
                    return !t.In(Value); ;
                case OperatorType.Each:

                    return false;
                default:
                    return false;
            }

        }
        public bool Check(float t)
        {
            if (ValueAsInit < 0) return false;
            switch (Operation)
            {
                case OperatorType.Equal: return t == ValueAsInit;
                case OperatorType.NotEqual: return t != ValueAsInit;
                case OperatorType.Less: return t < ValueAsInit;
                case OperatorType.LessEqual: return t <= ValueAsInit;
                case OperatorType.Greater: return t > ValueAsInit;
                case OperatorType.GreaterEqual: return t >= ValueAsInit;
                case OperatorType.In:
                case OperatorType.NotIn:
                    return false;
                case OperatorType.Each:

                    if (t >= ValueAsInit)
                    {
                        t -= ValueAsInit;
                        return true;
                    }


                    return false;
                default:
                    return false;
            }

        }
        public bool Check(Vector3 vector)
        {
            if (ValueAsInit < 0) return false;
            switch (Operation)
            {
                case OperatorType.Equal: return vector.x == ValueAsVector.x || vector.y == ValueAsVector.y;
                case OperatorType.NotEqual: return !(vector.x == ValueAsVector.x || vector.y == ValueAsVector.y);
                case OperatorType.Less: return vector.x < ValueAsVector.x || vector.y < ValueAsVector.y;
                case OperatorType.LessEqual: return vector.x <= ValueAsVector.x || vector.y <= ValueAsVector.y;
                case OperatorType.Greater: return vector.x > ValueAsVector.x || vector.y > ValueAsVector.y;
                case OperatorType.GreaterEqual: return vector.x >= ValueAsVector.x || vector.y >= ValueAsVector.y;
                case OperatorType.In:
                case OperatorType.NotIn:
                    return false;
                case OperatorType.Each:

                    //if (t >= ValueAsInit)
                    //{
                    //    t -= ValueAsInit;
                    //    return true;
                    //}


                    return false;
                default:
                    return false;
            }

        }
    }
}

